#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Helight");
//定义主设备号与次设备号
#define DP_MAJOR 250
#define DP_MINOR 0

//定义变量
static int char_read(struct file *filp, char __user *buffer, size_t, loff_t *);
static int char_open(struct inode *, struct file *);
static int char_write(struct file *filp, const char __user *buffer, size_t, loff_t *);
static int char_release(struct inode *, struct file *);
static int chropen;
struct cdev *chardev;
static int len;
//file_operations结构中的每个函数都对应一个具体的功能，也就是对设备的不同操作
static const struct file_operations char_ops =
    {
        .read = char_read,
        .write = char_write,
        .open = char_open,
        .release = char_release,
};
//设备驱动模块加载函数
static int __init char_init(void)
{
    dev_t dev;
    printk(KERN_ALERT "Initing......\n");
    dev = MKDEV(DP_MAJOR, DP_MINOR);
    chardev = cdev_alloc();
    if (chardev == NULL)
    {
        return -1;
    }
    if (register_chrdev_region(dev, 10, "chardev"))
    {
        printk(KERN_ALERT "Register char dev error\n");
        return -1;
    }
    chropen = 0;
    len = 0;
    cdev_init(chardev, &char_ops);
    if (cdev_add(chardev, dev, 1))
    {
        printk(KERN_ALERT "Add char dev error\n");
    }
    return 0;
}
//文件打开函数会在设备结构体指针赋值给私有数据
static int char_open(struct inode *inode, struct file *file)
{
    if (chropen == 0)
        chropen++;
    Else
    {
        printk(KERN_ALERT "Another process open the char device\n");
        return -1;
    }
    try_module_get(THIS_MODULE);
    return 0;
}
//释放函数
static int char_release(struct inode *inode, struct file *file)
{
    chropen--;
    module_put(THIS_MODULE);
    return 0;
}
//读函数
static int char_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
{
    if (length < 12)
    {
        if (!copy_to_user(buffer, "hello world!", length))
        {
            return 0;
        }
    }
    else
    {
        if (!copy_to_user(buffer, "hello world!", strlen(hello, world !"")))
        {
            return 0;
        }
    }
    return -1;
}
//写函数
static int char_write(struct file *filp, const char __user *buffer, size_t length, loff_t *offset)
{
    return 0;
}

//设备驱动模块卸载函数
static void __exit module_close(void)
{
    len = 0;
    printk(KERN_ALERT "Unloading..........\n");
    unregister_chrdev_region(MKDEV(DP_MAJOR, DP_MINOR), 10);
    cdev_del(chardev);
}
module_init(char_init);
module_exit(module_close);